#!/usr/bin/env python3
import json
import hashlib
import os
import threading
from flask import Flask, request, jsonify
import requests

class CacheServer:
    def __init__(self, node_id, port, all_nodes):
        self.node_id = node_id
        self.port = port
        self.all_nodes = all_nodes  # {node_id: (host, port)}
        self.cache = {}  # 内存缓存
        self.lock = threading.Lock()
        self.app = Flask(__name__)
        self.setup_routes()

    def _hash_key(self, key):
        """使用SHA256计算key的哈希值"""
        return int(hashlib.sha256(key.encode()).hexdigest(), 16)

    def _get_node_for_key(self, key):
        """根据key找到对应的节点"""
        hash_val = self._hash_key(key)
        node_ids = sorted(self.all_nodes.keys())
        # 简单的取模哈希
        return node_ids[hash_val % len(node_ids)]

    def setup_routes(self):
        @self.app.route('/', methods=['POST'])
        def set_value():
            """写入/更新缓存"""
            try:
                data = request.get_json()
                if not data or len(data) != 1:
                    return jsonify({"error": "Invalid request body"}), 400
                
                key = list(data.keys())[0]
                value = data[key]
                
                target_node = self._get_node_for_key(key)
                
                if target_node == self.node_id:
                    # 数据属于当前节点
                    with self.lock:
                        self.cache[key] = value
                    return jsonify({key: value}), 200
                else:
                    # 转发到目标节点
                    target_host, target_port = self.all_nodes[target_node]
                    response = requests.post(
                        f'http://{target_host}:{target_port}/',
                        json={key: value},
                        headers={'Content-Type': 'application/json'}
                    )
                    return response.content, response.status_code, response.headers.items()
                    
            except Exception as e:
                return jsonify({"error": str(e)}), 500

        @self.app.route('/<key>', methods=['GET'])
        def get_value(key):
            """读取缓存"""
            try:
                target_node = self._get_node_for_key(key)
                
                if target_node == self.node_id:
                    # 数据在当前节点
                    with self.lock:
                        if key in self.cache:
                            return jsonify({key: self.cache[key]}), 200
                        else:
                            return '', 404
                else:
                    # 从目标节点获取
                    target_host, target_port = self.all_nodes[target_node]
                    response = requests.get(
                        f'http://{target_host}:{target_port}/{key}',
                        headers={'Content-Type': 'application/json'}
                    )
                    return response.content, response.status_code, response.headers.items()
                    
            except Exception as e:
                return jsonify({"error": str(e)}), 500

        @self.app.route('/<key>', methods=['DELETE'])
        def delete_value(key):
            """删除缓存"""
            try:
                target_node = self._get_node_for_key(key)
                
                if target_node == self.node_id:
                    # 数据在当前节点
                    with self.lock:
                        if key in self.cache:
                            del self.cache[key]
                            return jsonify({"deleted": 1}), 200
                        else:
                            return jsonify({"deleted": 0}), 200
                else:
                    # 转发到目标节点
                    target_host, target_port = self.all_nodes[target_node]
                    response = requests.delete(
                        f'http://{target_host}:{target_port}/{key}',
                        headers={'Content-Type': 'application/json'}
                    )
                    return response.content, response.status_code, response.headers.items()
                    
            except Exception as e:
                return jsonify({"error": str(e)}), 500

    def run(self, host='0.0.0.0'):
        self.app.run(host=host, port=self.port, debug=False)

if __name__ == '__main__':
    import sys
    
    if len(sys.argv) != 3:
        print("Usage: python cache_server.py <node_id> <port>")
        sys.exit(1)
    
    node_id = sys.argv[1]
    port = int(sys.argv[2])
    
    # 固定3个节点的配置
    all_nodes = {
        'node1': ('cache1', 9527),
        'node2': ('cache2', 9528),
        'node3': ('cache3', 9529)
    }
    
    server = CacheServer(node_id, port, all_nodes)
    print(f"Cache server {node_id} starting on port {port}...")
    server.run()
